package top.itpath.admin.intercepter;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.extra.spring.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import top.itpath.admin.dto.TokenInfo;
import top.itpath.common.exp.NoAuthException;
import top.itpath.common.util.JwtUtil;
import top.itpath.common.util.RequestUtil;
import top.itpath.config.ApplicationProperties;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

/**
 * @author zhaomengru
 * @time 2023/10/10 - 23:23
 * <p>
 * 权限拦截器
 */
@Slf4j
@Component
public class PermissionInterceptor implements HandlerInterceptor {

    private final Set<String> ignoreUrls = new HashSet<>();
    private StringRedisTemplate redisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        if (CollectionUtil.isEmpty(ignoreUrls)) {
            ApplicationProperties properties = SpringUtil.getBean(ApplicationProperties.class);
            ignoreUrls.addAll(properties.getIgnoreUrls());
            ignoreUrls.forEach(url -> log.info("ignore url:{}", url));
        }
        if (Objects.isNull(redisTemplate)) {
            redisTemplate = SpringUtil.getBean(StringRedisTemplate.class);
        }
        if (ignoreUrls.contains(request.getRequestURI())) {
            return true;
        }
        // 检查token是否在黑名单中
        if (Boolean.TRUE.equals(redisTemplate.opsForSet().isMember(TokenInfo.BLOCK_TOKEN, RequestUtil.getToken()))) {
            throw new NoAuthException();
        }
        String token = RequestUtil.getToken(request);
        if (!StringUtils.hasText(token)) {
            throw new NoAuthException();
        }
        JwtUtil.verifyToken(token);
        return true;
    }
}
